#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <iostream>
#include <queue>
#define THREADNUM 2
class Mythread
{
    public:
        Mythread()
        {
            //初始化锁
            pthread_cond_init(&g_cons_lock_,NULL);
            pthread_cond_init(&g_proc_lock_,NULL);
            pthread_mutex_init(&g_lock_,NULL);
            capacity_ = 10;
        }
        ~Mythread()
        {
            pthread_cond_destroy(&g_cons_lock_);
            pthread_cond_destroy(&g_proc_lock_);
            pthread_mutex_destroy(&g_lock_);
        }
        //生产者线程
        void Push(int date)
        {
            pthread_mutex_lock(&g_lock_);
            while(que_.size()>=capacity_)
            {
                pthread_cond_wait(&g_proc_lock_,&g_lock_);
            }
            que_.push(date);
            pthread_mutex_unlock(&g_lock_);
            pthread_cond_signal(&g_cons_lock_);

        }
        //消费者线程
        void Pop(int* date)
        {
            pthread_mutex_lock(&g_lock_);
            while(que_.empty())
            {
                pthread_cond_wait(&g_cons_lock_,&g_lock_);
            }
            *date = que_.front();
            que_.pop();
            printf("i am consumer:%p,i consum : %d\n",pthread_self(),*date);
            pthread_mutex_unlock(&g_lock_);
            pthread_cond_signal(&g_proc_lock_);
        }
    private:
        std::queue<int> que_;
        size_t capacity_;
        pthread_mutex_t g_lock_;
        pthread_cond_t g_cons_lock_;
        pthread_cond_t g_proc_lock_;
};

pthread_mutex_t lock_;
int g_date=1;
//消费入口
void* ConsStart(void* arg)
{
    Mythread* md = (Mythread*)arg;
    while(1)
    {
        int date;
        md->Pop(&date);
    }
}


//生产入口
void* ProcStart(void* arg)
{
    Mythread* md = (Mythread*)arg;
    while(1)
    {
        md->Push(g_date);
        pthread_mutex_lock(&lock_);
        g_date++;
        pthread_mutex_unlock(&lock_);
        sleep(1);
    }
    return NULL;
}


int  main()
{
    pthread_mutex_init(&lock_,NULL);
    Mythread* md = new Mythread();
    if(md == NULL)
    {
        perror("Mythread\n");
        return 0; 
    }

    pthread_t cons[THREADNUM],proc[THREADNUM],proc1[THREADNUM];//,proc1[THREADNUM];
    for(int i = 0;i < THREADNUM;i++)
    {
        int ret = pthread_create(&cons[i],NULL,ConsStart,(void*)md);
        if(ret < 0)
        {
            perror("create\n");
            return 0;
        }
        ret = pthread_create(&proc[i],NULL,ProcStart,(void*)md);
        if(ret < 0)
        {
            perror("create\n");
            return 0;
        }

        ret = pthread_create(&proc1[i],NULL,ProcStart,(void*)md);
        if(ret < 0)
        {
            perror("create\n");
            return 0;
        }

    }
    for(int i = 0;i < THREADNUM;i++)
    {
        pthread_join(cons[i],NULL);
        pthread_join(proc[i],NULL);
        pthread_join(proc1[i],NULL);
        // pthread_join(proc1[0],NULL);
    }
    pthread_mutex_destroy(&lock_);
    return 0;
}
